package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.OrdersPageQueryDTO;
import com.sky.dto.OrdersSubmitDTO;
import com.sky.entity.AddressBook;
import com.sky.entity.OrderDetail;
import com.sky.entity.Orders;
import com.sky.entity.ShoppingCart;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.OrderBusinessException;
import com.sky.exception.ShoppingCartBusinessException;
import com.sky.mapper.UserAddressMapper;
import com.sky.mapper.UserOrderDetailMapper;
import com.sky.mapper.UserOrderMapper;
import com.sky.mapper.UserShoppingCartMapper;
import com.sky.service.UserOrderService;
import com.sky.vo.OrderDetailVO;
import com.sky.vo.OrderSearchPageVO;
import com.sky.vo.OrderSubmitVO;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import com.sky.vo.UserOrderSearchPageVO;
import com.sky.websocket.WebSocketServer;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;




@Service
@RequiredArgsConstructor

public class UserOrderServiceImpl implements UserOrderService {

    private final UserOrderMapper userOrderMapper;
    private final UserAddressMapper userAddressMapper;
    private final UserShoppingCartMapper userShoppingCartMapper;
    private final UserOrderDetailMapper userOrderDetailMapper;
    private final WebSocketServer webSocketServer;

    @Transactional
    @Override
    public OrderSubmitVO submit(OrdersSubmitDTO ordersSubmitDTO) {

        AddressBook addressBook = userAddressMapper.selectAddressInfoById(ordersSubmitDTO.getAddressBookId());
        if (Objects.isNull(addressBook)){
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }

        ShoppingCart shoppingCart = new ShoppingCart();
        shoppingCart.setUserId(BaseContext.getCurrentId());
        List<ShoppingCart> shoppingCarts = userShoppingCartMapper.selectShoppingCart(BaseContext.getCurrentId());
        if (CollectionUtils.isEmpty(shoppingCarts)){
            throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
        }

        Orders orders = new Orders();
        String number = String.valueOf(System.currentTimeMillis());
        orders.setNumber(number);
        orders.setStatus(Orders.PENDING_PAYMENT);
        orders.setUserId(BaseContext.getCurrentId());
        orders.setAddressBookId(ordersSubmitDTO.getAddressBookId());
        orders.setPayMethod(ordersSubmitDTO.getPayMethod());
        orders.setPayStatus(Orders.UN_PAID);

        orders.setOrderTime(LocalDateTime.now());
        BigDecimal amount = new BigDecimal("0");
        for (int i = 0; i < shoppingCarts.size(); i++) {
            amount = amount.add(shoppingCarts.get(i).getAmount());
        }
        orders.setAmount(amount);
        orders.setRemark(ordersSubmitDTO.getRemark());
        orders.setUserName(addressBook.getConsignee());
        orders.setPhone(addressBook.getPhone());
        String address = addressBook.getProvinceName() + addressBook.getCityName() + addressBook.getDistrictName() + addressBook.getDetail();
        orders.setAddress(address);
        orders.setConsignee(addressBook.getConsignee());

        orders.setCancelReason(orders.getCancelReason());
        orders.setRejectionReason(orders.getRejectionReason());
        orders.setDeliveryStatus(ordersSubmitDTO.getDeliveryStatus());
        orders.setPackAmount(ordersSubmitDTO.getPackAmount());
        orders.setTablewareNumber(ordersSubmitDTO.getTablewareNumber());
        orders.setTablewareStatus(ordersSubmitDTO.getTablewareStatus());

        userOrderMapper.insertOrders(orders);

        List<OrderDetail> orderDetailList = shoppingCarts.stream().map(item -> {
            OrderDetail orderDetail = new OrderDetail();
            BeanUtils.copyProperties(item,orderDetail);
            orderDetail.setOrderId(orders.getId());
            return orderDetail;
        }).collect(Collectors.toList());

        userOrderDetailMapper.insertBatch(orderDetailList);

        userShoppingCartMapper.cleanShoppingCart(BaseContext.getCurrentId());

        OrderSubmitVO orderSubmitVO = new OrderSubmitVO();
        orderSubmitVO.setId(orders.getId());
        orderSubmitVO.setOrderNumber(number);
        orderSubmitVO.setOrderAmount(amount);
        orderSubmitVO.setOrderTime(orders.getOrderTime());

        return orderSubmitVO;
    }

    @Override
    public UserOrderSearchPageVO historyOrders(OrdersPageQueryDTO ordersPageQueryDTO) {
        PageHelper.startPage(ordersPageQueryDTO.getPage(),ordersPageQueryDTO.getPageSize());
        ordersPageQueryDTO.setUserId(BaseContext.getCurrentId());
        List<OrderDetailVO> orders = userOrderMapper.selectByStatus(ordersPageQueryDTO.getStatus(),ordersPageQueryDTO.getUserId());

        PageInfo<OrderDetailVO> pageInfo = PageInfo.of(orders);
        List<OrderDetailVO> ordersList = pageInfo.getList();

        UserOrderSearchPageVO userOrderSearchPageVO = new UserOrderSearchPageVO();
        ordersList.forEach(orders1 -> {
            List<OrderDetail> orderDetailList = userOrderDetailMapper.selectByOrderId(orders1.getId());
            orders1.setOrderDetailList(orderDetailList);
        });
        userOrderSearchPageVO.setTotal(pageInfo.getTotal());
        userOrderSearchPageVO.setRecords(ordersList);
        return userOrderSearchPageVO;
    }

    @Override
    public Orders selectUserOrderDetailById(Long id) {
        Orders orders = userOrderMapper.selectById(id);
        if (Objects.isNull(orders)){
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }
        List<OrderDetail> orderDetailList = userOrderDetailMapper.selectByOrderId(orders.getId());
        orders.setOrderDetailList(orderDetailList);
        return orders;
    }

    @Override
    public void cancelOrderById(Long id) {
        Orders orders = userOrderMapper.selectById(id);
        if (Objects.isNull(orders)){
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }
        //查询订单状态是否大于2,如果大于2无法取消
        if(orders.getStatus() > 2){
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
        //todo 订单状态若处于待接单状态,需要退款

        //更改订单状态、取消原因、取消时间
        orders.setStatus(orders.CANCELLED);
        orders.setCancelReason("用户取消");
        orders.setCancelTime(LocalDateTime.now());

        userOrderMapper.updateOrders(orders);

    }

    @Override
    public void repetitionById(Long id) {
        //将原来的订单详情信息添加到购物车中
        List<OrderDetail> orderDetailList = userOrderDetailMapper.selectByOrderId(id);
        // todo 2.将订单详情信息转换为购物车信息
        List<ShoppingCart> shoppingCartList = orderDetailList.stream().map(orderDetail -> {
            ShoppingCart shoppingCart = new ShoppingCart();
            BeanUtils.copyProperties(orderDetail, shoppingCart);
            shoppingCart.setUserId(BaseContext.getCurrentId());
            shoppingCart.setCreateTime(LocalDateTime.now());
            return shoppingCart;
        }).collect(Collectors.toList());

        userShoppingCartMapper.insertBatch(shoppingCartList);

    }

    @Override
    public void paySuccess(String number) {
        Orders orders = new Orders();
        orders.setNumber(number);
        orders.setStatus(Orders.TO_BE_CONFIRMED);
        orders.setCheckoutTime(LocalDateTime.now());
        orders.setPayStatus(1);
        userOrderMapper.updateOrdersByNumber(orders);

        Orders order = userOrderMapper.selectByNumber(number);
        HashMap<String,Object> params = new HashMap<>();
        params.put("type",1);
        params.put("orderId",order.getId());
        params.put("content","订单号：" + number);
        webSocketServer.sendToAllClient(JSON.toJSONString(params));
    }

    @Override
    public void reminder(Long orderId) {
        HashMap<String,Object> params = new HashMap<>();
        params.put("type",2);
        params.put("orderId",orderId);
        params.put("content","订单号：" + orderId);
        webSocketServer.sendToAllClient(JSON.toJSONString(params));
    }
}
